#include <iostream>
#include <unistd.h>
#include <string>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>

// 通过管道实现父子进程之间的通信
int main()
{
    // 1. 创建管道
    int pipefd[2] = {0};  // 创建的管道文件对应的文件描述符
    int n = pipe(pipefd); // 创建管道

    if (n == -1) // 检查管道是否创建成功
    {
        perror("pipe");
        exit(1);
    }

    // 2. 创建子进程
    pid_t id = fork(); // 调用系统接口创建子进程
    if (id < 0)        // 子进程创建失败
    {
        perror("fork");
        exit(1);
    }
    else if (id == 0) // 子进程代码
    {
        // 3.子进程代码 -- 用于数据读取
        // 3.1 关闭不需要的fd -- 子进程关闭写
        close(pipefd[1]);

        // 3.2 创建用于读取的缓冲区并读入数据
        char read_buffer[1024 * 8] = {0};
        //char read_buffer[1024] = {0};

        int count = 0;
        while (true)
        {
            //sleep(5);
            ssize_t sz = read(pipefd[0], read_buffer, 1024 * 8);
            // 3.3 输出读取到的数据
            if (sz > 0)
            {
                read_buffer[sz] = '\0';
                std::cout << "Father# " << read_buffer << " " << ++count << std::endl;
            }
            else  //sz == 0
            {
                std::cout << "write process[Father] close" << std::endl;
                break;
            }
            
            std::cout << "count:" << count << std::endl;
            if(count == 5) break;

            sleep(1);
        }

        close(0);
        exit(0);
    }

    // 3. 父进程代码 -- 负责写数据
    // 3.1 关闭不需要的fd，父进程关闭读
    close(pipefd[0]);
    char send_buffer[8 * 1024] = {0};    //用于写数据的缓冲区

    // 3.2 写数据并计数
    // 如果写数据的进程退出，而读数据的进程没有退出，那么读数据进程中的read返回0
    // 如果读数据的进程退出而写数据的进程没有退出，那么OS直接终止进程
    int count = 0;
    while(true)
    {
        std::string message = "I'm Father Process, I'm writing data to you";
        snprintf(send_buffer, 1024 * 8, "%s:%d ", message.c_str(), ++count);

        //向fd中写数据
        ssize_t sz = write(pipefd[1], send_buffer, strlen(send_buffer));
        //ssize_t sz = write(pipefd[1], send_buffer, 1024 * 8);

        //std::cout << count << std::endl;
        // if(count == 5) 
        // {
        //     std::cout << "end write" << std::endl;
        //     break;
        // }

        sleep(1);
    }

    close(pipefd[1]);

    // 4. 阻塞等待子进程退出
    int status = 0;
    pid_t ret = waitpid(id, &status, 0);

    if(WIFEXITED(status) > 0)
    {
        printf("exit success, exit code:%d\n", WEXITSTATUS(status));
    }

    return 0;
}